import 'dart:convert';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../models/playlist.dart';
import '../models/song.dart';

class PlaylistManagementService {
  static const String _playlistsKey = 'custom_playlists';

  // 监听支持：页面可订阅歌单变更以实时刷新
  static final List<VoidCallback> _listeners = [];
  static void addListener(VoidCallback listener) {
    _listeners.add(listener);
  }
  static void removeListener(VoidCallback listener) {
    _listeners.remove(listener);
  }
  static void _notifyListeners() {
    for (final l in List<VoidCallback>.from(_listeners)) {
      try {
        l();
      } catch (_) {}
    }
  }

  static Future<List<Playlist>> getPlaylists() async {
    final prefs = await SharedPreferences.getInstance();
    final raw = prefs.getString(_playlistsKey);
    if (raw == null || raw.isEmpty) return [];
    final list = jsonDecode(raw) as List;
    return list
        .map((e) => Playlist.fromJson(e as Map<String, dynamic>))
        .toList();
  }

  static Future<void> _savePlaylists(List<Playlist> playlists) async {
    final prefs = await SharedPreferences.getInstance();
    final data = jsonEncode(playlists.map((p) => p.toJson()).toList());
    await prefs.setString(_playlistsKey, data);
    _notifyListeners();
  }

  static Future<Playlist> createPlaylist(String name) async {
    final playlists = await getPlaylists();
    final id = DateTime.now().millisecondsSinceEpoch.toString();
    final playlist = Playlist(id: id, name: name, songs: []);
    playlists.add(playlist);
    await _savePlaylists(playlists);
    return playlist;
  }

  static Future<void> renamePlaylist(String id, String newName) async {
    final playlists = await getPlaylists();
    for (final p in playlists) {
      if (p.id == id) {
        p.name = newName;
        break;
      }
    }
    await _savePlaylists(playlists);
  }

  static Future<void> deletePlaylist(String id) async {
    final playlists = await getPlaylists();
    playlists.removeWhere((p) => p.id == id);
    await _savePlaylists(playlists);
  }

  static Future<Playlist?> getPlaylistById(String id) async {
    final playlists = await getPlaylists();
    try {
      return playlists.firstWhere((p) => p.id == id);
    } catch (_) {
      return null;
    }
  }

  static Future<List<Song>> getPlaylistSongs(String id) async {
    final p = await getPlaylistById(id);
    return p?.songs ?? [];
  }

  static Future<void> addSongTo(String id, Song song) async {
    final playlists = await getPlaylists();
    for (final p in playlists) {
      if (p.id == id) {
        final idx = p.songs.indexWhere(
          (s) => s.effectiveId == song.effectiveId && s.source == song.source,
        );
        if (idx >= 0) {
          p.songs[idx] = song; // 覆盖同曲
        } else {
          p.songs.add(song); // 追加不同
        }
        break;
      }
    }
    await _savePlaylists(playlists);
  }

  static Future<void> removeSongFrom(String id, Song song) async {
    final playlists = await getPlaylists();
    for (final p in playlists) {
      if (p.id == id) {
        p.songs.removeWhere(
          (s) => s.effectiveId == song.effectiveId && s.source == song.source,
        );
        break;
      }
    }
    await _savePlaylists(playlists);
  }

  static Future<String> exportPlaylistToFile({required String id, required String filePath}) async {
    final songs = await getPlaylistSongs(id);
    final data = jsonEncode(songs.map((s) => s.toJson()).toList());
    final file = File(filePath);
    await file.writeAsString(data);
    return file.path;
  }

  static Future<int> importPlaylistFromFile({required String id, required String filePath}) async {
    final file = File(filePath);
    if (!await file.exists()) return 0;
    final content = await file.readAsString();
    final list = jsonDecode(content) as List;
    final songs = list.map((e) => Song.fromJson(e as Map<String, dynamic>)).toList();

    final playlists = await getPlaylists();
    final pIndex = playlists.indexWhere((p) => p.id == id);
    if (pIndex < 0) return 0;
    final target = playlists[pIndex];

    for (final song in songs) {
      final idx = target.songs.indexWhere(
        (s) => s.effectiveId == song.effectiveId && s.source == song.source,
      );
      if (idx >= 0) {
        target.songs[idx] = song;
      } else {
        target.songs.add(song);
      }
    }

    await _savePlaylists(playlists);
    return songs.length;
  }
}